Function.prototype.call = function (context,...arg) {
    // 将要调用的函数作为某个对象下的属性。
    // 一旦调用函数，那么该函数中的this会被隐式绑定为对象
    const cTypeof = typeof context;// fn2  ---->function
    const typeArr = ["string", "number", "boolean"]
    if (typeArr.includes(cTypeof)) {
        context = new Object(context);
    }
    else if (context === undefined || context === null) {
        context = window;
    }

    const fnName = Math.random().toString(36).slice(2);// xxxxxx  jjjjjj
    Object.prototype[fnName] = this;// Object.prototype.xxxxx = this---->fn1.call  fn2
    const result = context[fnName](...arg);// fn2.xxxx(); window.jjjjj()
    delete Object.prototype[fnName];
    return result;
}
Function.prototype.apply = function(context){
    const cTypeof = typeof context;
    const typeArr = ["string", "number", "boolean"]
    if (typeArr.includes(cTypeof)) {
        context = new Object(context);
    } else if (context === undefined || context === null) {
        context = window;
    }
    const fnName = Math.random().toString(36).slice(2);
    Object.prototype[fnName] = this;

    // let arg = [];
    // if(Array.isArray(arguments[1])){
    //     arg = arguments[1];
    // }else if(arguments[1] !== undefined){
    //     // 不是数组也不是undefined
    //     throw "数据类型异常";
    // }

    // 建议：
    const arg = arguments[1] || [];
    const result = eval("context[fnName]("+arg.join(",")+")");// context[fnName](1,2)
    delete Object.prototype[fnName];
    return result;
}
Function.prototype.bind = function(context){
    // 未优化
    // const cTypeof = typeof context;
    // const typeArr = ["string", "number", "boolean"];
    // if(typeArr.includes(cTypeof)) context = new Object(context);
    // else if(context === undefined || context === null) context = window;
    // const fnName = Math.random().toString(36).slice(2);
    // const _this = this;
    // const arg1 = Array.from(arguments).slice(1);
    // return function(){
    //     const arg = arg1.concat(Array.from(arguments));
    //     Object.prototype[fnName] = _this;
    //     // context[fnName](arg);
    //     eval("context[fnName]("+arg.join(",")+")")
    //     delete Object.prototype[fnName];
    // }

    // 优化
    const _this = this;
    const arg1 = Array.from(arguments).slice(1);
    return function(){
        const arg = arg1.concat(Array.from(arguments));
        return _this.apply(context,arg);
    }
}
